/*
 *
 * C++ MaJiang for 血流红中
 *
 * TuyooGame, 2021
 * zhouxin@tuyoogame.com
 *
 */
#ifndef __MJ_TILES__
#define __MJ_TILES__

#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <algorithm>
#include <time.h>
#include "mjdata.h"
#include "mj_define.h"
#include "mj_helper.h"
#include <combinations.hpp>

using iter::combinations;
using namespace std;

//判断isHu的基本工具类
//预先对牌做了桶容器统计处理
//算番时也大量用到了
class Tiles {
public:
    uint8_t tiles[32];
    uint8_t tiles_len;

    set<uint8_t> laizi;
    bool is_zishun;

    uint8_t laizi_count;

    //记录n张牌的个数，例如count_all[4]表示4张的个数
    //all包含风箭,noz不包含
    //有些特殊情况会出现6张，比如6张红中，所以留了32个位置
    uint8_t count_all[32];
    uint8_t count_noz[32];

    //MJ_COUNTER定义参见mj.h
    //存储了某种类型牌的总张数，以及用桶存储各牌的张数
    //非字牌的,wan tiao tong联合
    MJ_COUNTER counter_noz; 
    //字牌的联合
    MJ_COUNTER counter_z;
    //wan, tiao, tong, feng, jian;
    MJ_COUNTER counter[5];

    uint64_t shape_z, shape_noz;

    Tiles();
    Tiles(vector<uint8_t> &t, vector<uint8_t> &l, bool is_zishun = false);
    ~Tiles();

    //用assign的模式，节省对象创建的开销，建议Tiles实例重复利用
    bool assign(vector<uint8_t> &t, vector<uint8_t> &l, bool is_zishun = false);

    bool findTile(uint8_t t);

    MJ_TILE_TYPE getType(uint8_t t);

    //one可以取-1，用于删除模式，暂时没用到one=-1...
    bool countTiles(int one = 1);

    //isHu主要基于shape查表方式
    uint64_t shape(uint8_t ts[], uint8_t tslen);
    uint64_t makeBuShape(uint8_t ts[], uint8_t tslen);
    tuple<bool, uint8_t, bool> partBuShape(uint64_t s, uint8_t laizin, bool jiang=false, bool zi=false);
    tuple<bool, uint8_t, bool> split00Shape(uint64_t s, uint8_t laizin, bool jiang);
    tuple<bool, uint8_t, bool> noSplitShape(uint64_t s, int8_t laizin, bool jiang);
    tuple<bool, uint8_t, bool> checkShapeComHu(vector<uint64_t> &s, uint8_t laizin, bool jiang);
    vector<tuple<bool, uint8_t, bool>> lastSplitShape(uint64_t s, uint8_t laizin, bool jiang);
    bool isHu();

    //获取所有牌表放到v中,排除掉filter
    void getHands(vector<uint8_t> &v, uint8_t filter=255);

    //获取所有的非字牌放到v里,排除掉filter
    void getHandsNoZi(vector<uint8_t> &v, uint8_t filter=255);

    bool isLaiZi(uint8_t tile);
    //uint8_t getLaiZiCount();
};

#endif
